@file:Suppress("unused")

package han.cirno.corrupt.funny

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.util.TypedValue
import kotlin.random.Random

class LoginSurface: BaseSurface {
    data class Ball(var x:Float,var y:Float,val r:Float,var color:Int){
        var vx:Float=0f
        var vy:Float=0f
        var lifeTime:Long=0
        var a:Float=1f
        var boost:Float=1f
    }
    var centerColor:IntArray?= null//Color.rgb(0,23,170),Color.BLUE )
    var speedFactor=1f
    var boostFactor=1f
    private var targetSpeedFactor=speedFactor
    private var targetCenterColor:IntArray?=null
    private val offsetFactor=30
    private var backgroundColor:Int=run{
        val typedValue = TypedValue()
        context.theme.resolveAttribute(android.R.attr.colorBackground,typedValue,true)
        typedValue.data
    }
    private val balls=ArrayList<Ball>()
    private val paint:Paint=Paint()

    constructor(context: Context?) : super(context)
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    )
    constructor(
        context: Context?,
        attrs: AttributeSet?,
        defStyleAttr: Int,
        defStyleRes: Int
    ) : super(context, attrs, defStyleAttr, defStyleRes)

    override fun loop(canvas: Canvas, deltaTimeMs: Long) {
        ballLoop(deltaTimeMs)
        canvas.drawColor(backgroundColor)
        balls.forEach {
            var color = it.color
            color=(color and 0x00FFFFFF) or (((color.toLong() and 0xFF000000 shr 24).toFloat()*it.a).toInt() and 0xFF shl 24)
            paint.color= color
            canvas.drawCircle(it.x,it.y,it.r,paint)
        }
    }

    private fun ballLoop(deltaTimeMs: Long){
        val speedFactorChanged=speedFactor>=targetSpeedFactor
        val speedFactorChangeFactor=speedFactor/targetSpeedFactor
        val boostFactorChangeFactor=boostFactor
        if (boostFactorChangeFactor!=1f) {
            boostFactor = 1f
            balls.forEach{
                it.boost=boostFactorChangeFactor
            }
        }
        targetCenterColor=centerColor
        targetSpeedFactor=speedFactor
        balls.iterator().let {
            while (it.hasNext()){
                val next = it.next()
                next.lifeTime-=deltaTimeMs
                if (next.lifeTime<=1000){
                    next.a=next.lifeTime/1000f
                }
                if (next.lifeTime<=0
                    || next.x !in 0f..canvasWidth.toFloat()
                    || next.y !in 0f..canvasHeight.toFloat())it.remove()
            }
        }
        balls.forEach {
            it.x+=deltaTimeMs.toFloat()*it.vx/1000f*it.boost
            it.y+=deltaTimeMs.toFloat()*it.vy/1000f*it.boost
            it.boost+=(it.boost-1)/70f
            if (speedFactorChanged) {
                it.vx *= speedFactorChangeFactor
                it.vy *= speedFactorChangeFactor
            }
        }
        if (balls.size>=400)return
        var color=if (targetCenterColor==null)
            Random.nextInt(0,0xFFFFFF)
        else {
            val c=targetCenterColor!![Random.nextInt(targetCenterColor!!.size)]
            ((((c and 0xFF0000) shr 16) + Random.nextInt(
                0,
                offsetFactor
            ) * (if (Random.nextBoolean()) 1 else -1)).fit(0..0xFF) shl 16) or
                    ((((c and 0x00FF00) shr 8) + Random.nextInt(
                        0,
                        offsetFactor
                    ) * (if (Random.nextBoolean()) 1 else -1)).fit(0..0xFF) shl 8) or
                    ((((c and 0x0000FF) shr 0) + Random.nextInt(
                        0,
                        offsetFactor
                    ) * (if (Random.nextBoolean()) 1 else -1)).fit(0..0xFF) shl 0)
        }
        color=color or (Random.nextInt(0x77,0xFF) shl 24)
        val element = Ball(width / 2f, height / 2f, Random.nextFloat()*5f+3,color)
        val speedFactor=Random.nextInt(20,50)*15f*targetSpeedFactor
        element.vx=Random.nextFloat()*speedFactor*if(Random.nextBoolean())1 else -1
        element.vy=Random.nextFloat()*speedFactor*if(Random.nextBoolean())1 else -1
        element.lifeTime=Random.nextLong(3000,10000)
        balls.add(element)
    }

    private fun Int.fit(range: IntRange):Int{
        return if(this<range.first)range.first else if(this>range.last+range.first)range.last+range.first else this
    }
}